package com.event.management.frontend.service.impl;

import com.event.management.frontend.domain.Event;
import com.event.management.frontend.domain.Ticket;
import com.event.management.frontend.domain.UserTicket;
import com.event.management.frontend.dto.UserTicketDTO;
import com.event.management.frontend.mapper.EventMapper;
import com.event.management.frontend.mapper.TicketMapper;
import com.event.management.frontend.mapper.UserTicketMapper;
import com.event.management.frontend.service.UserTicketService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户电子票服务实现类
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class UserTicketServiceImpl implements UserTicketService {

    private final UserTicketMapper userTicketMapper;
    private final EventMapper eventMapper;
    private final TicketMapper ticketMapper;

    @Override
    public List<UserTicketDTO> getUserTickets(Long userId, int page, int size) {
        // 计算偏移量
        int offset = (page - 1) * size;
        
        // 查询用户电子票
        List<UserTicket> tickets = userTicketMapper.selectByUserId(userId);
        if (tickets.isEmpty()) {
            return java.util.Collections.emptyList();
        }
        
        // 只返回当前分页的数据
        tickets = tickets.stream()
                .skip(offset)
                .limit(size)
                .collect(Collectors.toList());
        
        // 转换为DTO
        return tickets.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    @Override
    public long countUserTickets(Long userId) {
        List<UserTicket> tickets = userTicketMapper.selectByUserId(userId);
        return tickets.size();
    }

    @Override
    public List<UserTicketDTO> getTicketsByOrderId(Long orderId) {
        List<UserTicket> tickets = userTicketMapper.selectByOrderId(orderId);
        return tickets.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    @Override
    public UserTicketDTO getTicketDetail(Long userId, Long ticketId) {
        UserTicket ticket = userTicketMapper.selectById(ticketId);
        if (ticket == null || !ticket.getUserId().equals(userId)) {
            throw new RuntimeException("电子票不存在或无权查看");
        }
        
        return convertToDTO(ticket);
    }

    @Override
    public UserTicketDTO getTicketByCode(String ticketCode) {
        UserTicket ticket = userTicketMapper.selectByTicketCode(ticketCode);
        if (ticket == null) {
            throw new RuntimeException("电子票不存在");
        }
        
        return convertToDTO(ticket);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean checkTicket(String ticketCode) {
        // 1. 查询电子票
        UserTicket ticket = userTicketMapper.selectByTicketCode(ticketCode);
        if (ticket == null) {
            log.error("验票失败: 电子票不存在, ticketCode={}", ticketCode);
            return false;
        }
        
        // 2. 检查电子票状态
        if (!"valid".equals(ticket.getStatus())) {
            log.error("验票失败: 电子票状态异常, ticketCode={}, status={}", ticketCode, ticket.getStatus());
            return false;
        }
        
        // 3. 检查活动时间是否有效
        Event event = eventMapper.selectById(ticket.getEventId());
        LocalDateTime now = LocalDateTime.now();
        
        if (now.isAfter(event.getEndTime())) {
            log.error("验票失败: 活动已结束, ticketCode={}", ticketCode);
            return false;
        }
        
        // 4. 更新电子票状态为已使用
        int rows = userTicketMapper.updateStatus(ticket.getId(), "used");
        if (rows <= 0) {
            log.error("验票失败: 更新状态失败, ticketCode={}", ticketCode);
            return false;
        }
        
        log.info("验票成功: ticketCode={}, ticketId={}", ticketCode, ticket.getId());
        return true;
    }
    
    /**
     * 用户自行标记电子票为已使用
     * @param userId 用户ID
     * @param ticketId 电子票ID
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean markTicketAsUsed(Long userId, Long ticketId) {
        // 1. 查询电子票
        UserTicket ticket = userTicketMapper.selectById(ticketId);
        if (ticket == null) {
            log.error("标记票为已使用失败: 电子票不存在, ticketId={}", ticketId);
            return false;
        }
        
        // 2. 验证电子票所属用户
        if (!ticket.getUserId().equals(userId)) {
            log.error("标记票为已使用失败: 无权操作此电子票, userId={}, ticketId={}", userId, ticketId);
            return false;
        }
        
        // 3. 检查电子票状态
        if (!"valid".equals(ticket.getStatus())) {
            log.error("标记票为已使用失败: 电子票状态异常, ticketId={}, status={}", ticketId, ticket.getStatus());
            return false;
        }
        
        // 4. 检查活动时间是否有效
        Event event = eventMapper.selectById(ticket.getEventId());
        LocalDateTime now = LocalDateTime.now();
        
        if (now.isAfter(event.getEndTime())) {
            log.error("标记票为已使用失败: 活动已结束, ticketId={}", ticketId);
            return false;
        }
        
        // 5. 更新电子票状态为已使用
        int rows = userTicketMapper.updateStatus(ticket.getId(), "used");
        if (rows <= 0) {
            log.error("标记票为已使用失败: 更新状态失败, ticketId={}", ticketId);
            return false;
        }
        
        log.info("用户成功标记电子票为已使用: userId={}, ticketId={}", userId, ticketId);
        return true;
    }
    
    /**
     * 将电子票实体转换为DTO
     */
    private UserTicketDTO convertToDTO(UserTicket ticket) {
        // 查询活动信息
        Event event = eventMapper.selectById(ticket.getEventId());
        
        // 查询票种信息
        Ticket ticketType = ticketMapper.selectById(ticket.getTicketId());
        
        // 转换状态
        int status;
        switch (ticket.getStatus()) {
            case "valid":
                status = 0; // 未使用
                break;
            case "used":
                status = 1; // 已使用
                break;
            case "cancelled":
                status = 3; // 已取消
                break;
            default:
                status = 0;
        }
        
        // 构建DTO
        return UserTicketDTO.builder()
                .id(ticket.getId())
                .userId(ticket.getUserId())
                .orderId(ticket.getOrderId())
                .eventId(ticket.getEventId())
                .eventName(event.getTitle())
                .ticketTypeId(ticket.getTicketId())
                .ticketTypeName(ticketType.getName())
                .ticketCode(ticket.getTicketCode())
                .price(ticketType.getPrice().multiply(new BigDecimal("100")).intValue())
                .eventStartTime(event.getStartTime())
                .eventEndTime(event.getEndTime())
                .eventVenue(event.getLocation())
                .status(status)
                .createTime(ticket.getCreatedAt().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime())
                .questionnaireAnswered(ticket.getQuestionnaireAnswered() != null ? ticket.getQuestionnaireAnswered() : 0)
                .build();
    }
} 